﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Net;
using System.Text.RegularExpressions;

namespace CodePlexNewReleaseChecker
{
    public class RssFeedReleases : IReleaseNamesProvider
    {
        private static string _baseRSSFeedURL = "http://{0}.codeplex.com/project/feeds/rss?ProjectRSSFeed=codeplex%3a%2f%2frelease%2f{0}";

        public List<BareRelease> GetReleaseNames(string projectName)
        {
            string _rssFeedURL = string.Format(_baseRSSFeedURL, projectName);

            IEnumerable<RSSChannel> chans = RSSChannel.ParseFromURL(new Uri(_rssFeedURL));
            //only one channel for codeplex releses
            RSSChannel releaseChannel = chans.First();

            return (from c in releaseChannel.Items
                    select new BareRelease()
                    {
                        Name = c.GetReleaseName(),
                        Link = c.Link
                    }).ToList();
        }


        //private classes used for RSS parsing
        //(inspired and heavily copied from http://www.codingday.com/rss-feed-parser-in-20-lines-with-net-linq/)
        internal class RSSChannel
        {
            public string Title { get; set; }
            public string Link { get; set; }
            public string Description { get; set; }
            public IEnumerable<RSSChannel.Item> Items { get; set; }

            public class Item
            {
                public string Title { get; set; }
                public string Link { get; set; }
                public string Description { get; set; }
                public string Guid { get; set; }
                public DateTime PublicationDate { get; set; }

                public string GetReleaseName()
                {
                    Regex nameReg = new Regex(".*?: (?<releaseName>.*?) \\(.*?\\)");
                    Group m = nameReg.Match(this.Title).Groups["releaseName"];

                    if (m == null) return string.Empty;

                    return m.Value;
                }
            }

            public static IEnumerable<RSSChannel> ParseFromURL(Uri rssUri)
            {
                //download rss feed
                WebClient client = new WebClient();
                string feed = client.DownloadString(rssUri);

                XDocument xdoc = XDocument.Parse(feed);

                return ParseFromXdoc(xdoc);
            }

            public static IEnumerable<RSSChannel> ParseFromXdoc(XDocument xdoc)
            {
                return (from channels in xdoc.Descendants("channel")
                        select new RSSChannel
                        {
                            Title = GetElementValue(channels, "title"),
                            Link = GetElementValue(channels, "link"),
                            Description = GetElementValue(channels, "description"),
                            Items = (from items in channels.Descendants("item")
                                     let title = GetElementValue(items, "title")
                                     where title.StartsWith("Released:") //filter out anything but released items
                                     select new RSSChannel.Item
                                     {
                                         Title = title,
                                         Link = GetElementValue(items, "link"),
                                         Description = GetElementValue(items, "description"),
                                         Guid = GetElementValue(items, "guid"),
                                         PublicationDate = Convert.ToDateTime(GetElementValue(items, "pubDate"))
                                     })
                        });
            }

            private static string GetElementValue(XElement e, string attr)
            {
                return e.Element(attr) != null ? e.Element(attr).Value : "";
            }
        }
    }
}
